package middleware

import (
	ct "context"
	"encoding/json"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"gopkg.in/ini.v1"
	"net/http"
	"strings"
	. "xm_shop/models"
	pb "xm_shop/proto/rbacRole"
)

// 管理员权限校验
func InitAdminAuthMiddleware(context *gin.Context) {
	// 进行权限判断, 没有登录的用户不能进入后台管理中心
	// 1. 获取访问的url地址
	pathname := context.Request.URL.Path // 获取纯后缀路径
	// 2. 获取session中保存的用户信息
	session := sessions.Default(context)
	userInfoOrNil := session.Get("userInfo")
	userInfoStr, ok := userInfoOrNil.(string)
	if ok {
		// 判断userInfo里面的信息是否存在
		var userInfo []Manager
		err := json.Unmarshal([]byte(userInfoStr), &userInfo)                 // 将字符串先转字节切片, 再转结构体切片, 可能会转换失败, 此时按照未登录处理
		if err != nil || !(len(userInfo) > 0 && userInfo[0].Username != "") { // 取反表示不合法的情况下, 按照没有登录处理
			if pathname != "/admin/login" && pathname != "/admin/captcha" {
				context.String(http.StatusOK, "重定向到登录界面")
				context.Abort() // 中断
			}
		} else { // 登录成功, 判断权限
			// 例如登出的路径, 需要登录, 但是没有权限限制
			// 去除路径前缀 /admin
			urlPath := strings.Replace(pathname, "/admin", "", 1)
			if userInfo[0].IsSuper == 0 && !excludeAuthPath(urlPath) { // 不是超级管理员且访问的路径不在白名单中
				/*
					// 获取当前角色对应的权限
					var roleAccessList []RoleAccess
					DB.Where("role_id = ?", userInfo[0].RoleID).Find(&roleAccessList)
					// 创建用户具有的权限的权限映射
					roleAccessMap := make(map[int]int)
					for _, v := range roleAccessList {
						roleAccessMap[v.AccessID] = v.AccessID
					}

					// 根据当前用户访问的路径检索权限表
					var access Access
					DB.Where("Url = ?", urlPath).Take(&access)
					if access.ID == 0 {
						context.String(http.StatusBadRequest, "路径不合法")
						context.Abort() // 中断
					}
					if _, ok := roleAccessMap[access.ID]; !ok {
						context.String(http.StatusBadRequest, "用户没有对应权限")
						context.Abort() // 中断
					}
				*/
				rbacClient := pb.NewRbacRoleService("rbac", MicroClient)
				res, _ := rbacClient.MiddleWareAuth(ct.Background(), &pb.MiddleWareAuthRequest{
					RoleId:  int64(userInfo[0].RoleID),
					UrlPath: urlPath,
				})
				if !res.HasPermission {
					context.String(http.StatusBadRequest, "用户没有对应权限")
					context.Abort() // 中断
				}
			}
		}
	} else {
		// 用户没登录
		// 判断是否是登录路径或者获取验证码路径
		if pathname != "/admin/login" && pathname != "/admin/captcha" {
			context.String(http.StatusOK, "重定向到登录界面")
			context.Abort() //中断
		}
	}
}

// 排除权限判断的方法
func excludeAuthPath(urlPath string) bool {
	// 读取ini 文件
	config, err := ini.Load("./conf/app.ini")
	if err != nil {
		fmt.Printf("fail to read file %v", err)
	}
	excludeAuthPathStr := config.Section("").Key("excludeAuthPath").String()
	// 转字符串切片
	excludeAuthPathSlice := strings.Split(excludeAuthPathStr, ",")
	// 循环遍历切片
	for _, v := range excludeAuthPathSlice {
		if urlPath == v {
			return true
		}
	}
	return false
}
